namespace PickGold.Charting.Utilities
{
	using System;
	using System.Collections;
	using System.ComponentModel;
	using System.Drawing;
	using System.Globalization;
	using System.IO;
	using System.Reflection;
	using PickGold.Charting;
	using System.Web.UI.WebControls;
	using System.Xml;

	internal class XmlFormatSerializer : SerializerBase
	{
		internal void Deserialize(object objectToDeserialize, Stream stream)
		{
			this.Deserialize(objectToDeserialize, stream);
		}

		internal void Deserialize(object objectToDeserialize, TextReader textReader)
		{
			this.Deserialize(objectToDeserialize, textReader);
		}

		internal override void Deserialize(object objectToDeserialize, object reader)
		{
			Stream input = reader as Stream;
			TextReader reader2 = reader as TextReader;
			XmlReader reader3 = reader as XmlReader;
			string inputUri = reader as string;
			if (objectToDeserialize == null)
			{
				throw new ArgumentNullException("objectToDeserialize");
			}
			if (reader == null)
			{
				throw new ArgumentNullException("reader");
			}
			if (((input == null) && (reader2 == null)) && ((reader3 == null) && (inputUri == null)))
			{
				throw new ArgumentException(SR.ExceptionChartSerializerReaderObjectInvalid, "reader");
			}
			XmlDocument xmlDocument = new XmlDocument();
			XmlReaderSettings settings = new XmlReaderSettings();
			settings.ProhibitDtd = true;
			if (input != null)
			{
				xmlDocument.Load(XmlReader.Create(input, settings));
			}
			if (inputUri != null)
			{
				xmlDocument.Load(XmlReader.Create(inputUri, settings));
			}
			if (reader3 != null)
			{
				xmlDocument.Load(XmlReader.Create(reader3, settings));
			}
			if (reader2 != null)
			{
				xmlDocument.Load(XmlReader.Create(reader2, settings));
			}
			if (base.IsResetWhenLoading)
			{
				this.ResetObjectProperties(objectToDeserialize);
			}
			this.DeserializeObject(objectToDeserialize, null, base.GetObjectName(objectToDeserialize), xmlDocument.DocumentElement, xmlDocument);
		}

		internal void Deserialize(object objectToDeserialize, string fileName)
		{
			this.Deserialize(objectToDeserialize, fileName);
		}

		internal void Deserialize(object objectToDeserialize, XmlReader xmlReader)
		{
			this.Deserialize(objectToDeserialize, xmlReader);
		}

		internal virtual int DeserializeObject(object objectToDeserialize, object parent, string elementName, XmlNode xmlParentNode, XmlDocument xmlDocument)
		{
			int num = 0;
			if (objectToDeserialize != null)
			{
				foreach (XmlAttribute attribute in xmlParentNode.Attributes)
				{
					if (!(attribute.Name == "_Template_") && base.IsSerializableContent(attribute.Name, objectToDeserialize))
					{
						this.SetXmlValue(objectToDeserialize, attribute.Name, attribute.Value);
						num++;
					}
				}
				IList list = objectToDeserialize as IList;
				if ((base.IsTemplateMode && (list != null)) && (xmlParentNode.FirstChild.Attributes["_Template_"] != null))
				{
					int num2 = 0;
					foreach (object obj2 in list)
					{
						XmlNode node = null;
						foreach (XmlNode node2 in xmlParentNode.ChildNodes)
						{
							string s = node2.Attributes["_Template_"].Value;
							if ((s != null) && (s.Length > 0))
							{
								if (s == "All")
								{
									node = node2;
									break;
								}
								int num3 = num2;
								while (num3 > (xmlParentNode.ChildNodes.Count - 1))
								{
									num3 -= xmlParentNode.ChildNodes.Count;
								}
								if (int.Parse(s, CultureInfo.InvariantCulture) == num3)
								{
									node = node2;
									break;
								}
							}
						}
						if (node != null)
						{
							this.DeserializeObject(obj2, objectToDeserialize, "", node, xmlDocument);
						}
						num2++;
					}
					return 0;
				}
				int num5 = 0;
				foreach (XmlNode node3 in xmlParentNode.ChildNodes)
				{
					if (list != null)
					{
						string itemName = null;
						if (node3.Attributes["Name"] != null)
						{
							itemName = node3.Attributes["Name"].Value;
						}
						bool reusedObject = false;
						object obj3 = base.GetListNewItem(list, node3.Name, ref itemName, ref reusedObject);
						int num6 = this.DeserializeObject(obj3, objectToDeserialize, "", node3, xmlDocument);
						num += num6;
						if ((num6 > 0) || reusedObject)
						{
							list.Insert(num5++, obj3);
						}
						continue;
					}
					if (base.IsSerializableContent(node3.Name, objectToDeserialize))
					{
						PropertyDescriptor descriptor = TypeDescriptor.GetProperties(objectToDeserialize)[node3.Name];
						if (descriptor != null)
						{
							object obj4 = descriptor.GetValue(objectToDeserialize);
							num += this.DeserializeObject(obj4, objectToDeserialize, node3.Name, node3, xmlDocument);
							continue;
						}
						if (!base.IsUnknownAttributeIgnored)
						{
							throw new InvalidOperationException(SR.ExceptionChartSerializerPropertyNameUnknown(node3.Name, objectToDeserialize.GetType().ToString()));
						}
					}
				}
			}
			return num;
		}

		protected string GetXmlValue(object obj, object parent, string elementName)
		{
			string str = obj as string;
			if (str != null)
			{
				return str;
			}
			Font font = obj as Font;
			if (font != null)
			{
				return SerializerBase.FontToString(font);
			}
			if (obj is Color)
			{
				return SerializerBase.colorConverter.ConvertToString(null, CultureInfo.InvariantCulture, obj);
			}
			Color[] colors = obj as Color[];
			if (colors != null)
			{
				return ColorArrayConverter.ColorArrayToString(colors);
			}
			if (obj is Unit)
			{
				Unit unit = (Unit)obj;
				return unit.Value.ToString(CultureInfo.InvariantCulture);
			}
			System.Drawing.Image image = obj as System.Drawing.Image;
			if (image != null)
			{
				return SerializerBase.ImageToString(image);
			}
			PropertyDescriptor pd = TypeDescriptor.GetProperties(parent)[elementName];
			if (pd != null)
			{
				TypeConverter converter = base.FindConverter(pd);
				if ((converter != null) && converter.CanConvertTo(typeof(string)))
				{
					return converter.ConvertToString(null, CultureInfo.InvariantCulture, obj);
				}
			}
			return obj.ToString();
		}

		private void RemoveEmptyChildNodes(XmlNode xmlNode)
		{
			for (int i = 0; i < xmlNode.ChildNodes.Count; i++)
			{
				this.RemoveEmptyChildNodes(xmlNode.ChildNodes[i]);
				XmlNode node = xmlNode.ChildNodes[i];
				if ((((node.ParentNode != null) && !(node.ParentNode is XmlDocument)) && !node.HasChildNodes) && ((node.Attributes == null) || (node.Attributes.Count == 0)))
				{
					xmlNode.RemoveChild(xmlNode.ChildNodes[i]);
					i--;
				}
				if ((!node.HasChildNodes && (node.Attributes.Count == 1)) && (node.Attributes["_Template_"] != null))
				{
					xmlNode.RemoveChild(xmlNode.ChildNodes[i]);
					i--;
				}
			}
		}

		internal void Serialize(object objectToSerialize, Stream stream)
		{
			this.Serialize(objectToSerialize, stream);
		}

		internal void Serialize(object objectToSerialize, TextWriter textWriter)
		{
			this.Serialize(objectToSerialize, textWriter);
		}

		internal override void Serialize(object objectToSerialize, object writer)
		{
			Stream outStream = writer as Stream;
			TextWriter writer2 = writer as TextWriter;
			XmlWriter w = writer as XmlWriter;
			string filename = writer as string;
			if (objectToSerialize == null)
			{
				throw new ArgumentNullException("objectToSerialize");
			}
			if (writer == null)
			{
				throw new ArgumentNullException("writer");
			}
			if (((outStream == null) && (writer2 == null)) && ((w == null) && (filename == null)))
			{
				throw new ArgumentException(SR.ExceptionChartSerializerWriterObjectInvalid, "writer");
			}
			XmlDocument xmlDocument = new XmlDocument();
			XmlDocumentFragment xmlParentNode = xmlDocument.CreateDocumentFragment();
			this.SerializeObject(objectToSerialize, null, base.GetObjectName(objectToSerialize), xmlParentNode, xmlDocument);
			xmlDocument.AppendChild(xmlParentNode);
			this.RemoveEmptyChildNodes(xmlDocument);
			if (outStream != null)
			{
				xmlDocument.Save(outStream);
				outStream.Flush();
				outStream.Seek(0L, SeekOrigin.Begin);
			}
			if (filename != null)
			{
				xmlDocument.Save(filename);
			}
			if (w != null)
			{
				xmlDocument.Save(w);
			}
			if (writer2 != null)
			{
				xmlDocument.Save(writer2);
			}
		}

		internal void Serialize(object objectToSerialize, string fileName)
		{
			this.Serialize(objectToSerialize, fileName);
		}

		internal void Serialize(object objectToSerialize, XmlWriter xmlWriter)
		{
			this.Serialize(objectToSerialize, xmlWriter);
		}

		protected virtual void SerializeCollection(object objectToSerialize, string elementName, XmlNode xmlParentNode, XmlDocument xmlDocument)
		{
			ICollection is2 = objectToSerialize as ICollection;
			if (is2 != null)
			{
				XmlNode newChild = xmlDocument.CreateElement(elementName);
				xmlParentNode.AppendChild(newChild);
				foreach (object obj2 in is2)
				{
					if (obj2 is DataPoint)
					{
						this.SerializeDataPoint(obj2, newChild, xmlDocument);
					}
					else
					{
						this.SerializeObject(obj2, objectToSerialize, base.GetObjectName(obj2), newChild, xmlDocument);
					}
				}
			}
		}

		internal void SerializeDataPoint(object objectToSerialize, XmlNode xmlParentNode, XmlDocument xmlDocument)
		{
			XmlNode newChild = xmlDocument.CreateElement(base.GetObjectName(objectToSerialize));
			xmlParentNode.AppendChild(newChild);
			DataPoint parent = objectToSerialize as DataPoint;
			if ((parent.XValue != 0.0) && base.IsSerializableContent("XValue", objectToSerialize))
			{
				XmlAttribute node = xmlDocument.CreateAttribute("XValue");
				node.Value = this.GetXmlValue(parent.XValue, parent, "XValue");
				newChild.Attributes.Append(node);
			}
			if ((parent.YValues.Length > 0) && base.IsSerializableContent("YValues", objectToSerialize))
			{
				XmlAttribute attribute2 = xmlDocument.CreateAttribute("YValues");
				attribute2.Value = this.GetXmlValue(parent.YValues, parent, "YValues");
				newChild.Attributes.Append(attribute2);
			}
			if (parent.IsEmpty && base.IsSerializableContent("IsEmpty", objectToSerialize))
			{
				XmlAttribute attribute3 = xmlDocument.CreateAttribute("IsEmpty");
				attribute3.Value = this.GetXmlValue(parent.isEmptyPoint, parent, "IsEmpty");
				newChild.Attributes.Append(attribute3);
			}
			bool flag = false;
			foreach (DictionaryEntry entry in parent.properties)
			{
				if (entry.Key is int)
				{
					string propertyName = ((CommonCustomProperties)((int)entry.Key)).ToString();
					if (base.IsSerializableContent(propertyName, objectToSerialize))
					{
						XmlAttribute attribute4 = xmlDocument.CreateAttribute(propertyName);
						attribute4.Value = this.GetXmlValue(entry.Value, parent, propertyName);
						newChild.Attributes.Append(attribute4);
					}
				}
				else
				{
					flag = true;
				}
			}
			if ((flag && !string.IsNullOrEmpty(parent.CustomProperties)) && base.IsSerializableContent("CustomProperties", objectToSerialize))
			{
				XmlAttribute attribute5 = xmlDocument.CreateAttribute("CustomProperties");
				attribute5.Value = this.GetXmlValue(parent.CustomProperties, parent, "CustomProperties");
				newChild.Attributes.Append(attribute5);
			}
		}

		protected virtual void SerializeObject(object objectToSerialize, object parent, string elementName, XmlNode xmlParentNode, XmlDocument xmlDocument)
		{
			if (objectToSerialize != null)
			{
				if (parent != null)
				{
					PropertyDescriptor descriptor = TypeDescriptor.GetProperties(parent)[elementName];
					if (descriptor != null)
					{
						SerializationVisibilityAttribute attribute = (SerializationVisibilityAttribute)descriptor.Attributes[typeof(SerializationVisibilityAttribute)];
						if ((attribute != null) && (attribute.Visibility == SerializationVisibility.Hidden))
						{
							return;
						}
					}
				}
				if (objectToSerialize is ICollection)
				{
					this.SerializeCollection(objectToSerialize, elementName, xmlParentNode, xmlDocument);
				}
				else
				{
					XmlNode newChild = xmlDocument.CreateElement(elementName);
					xmlParentNode.AppendChild(newChild);
					bool flag = false;
					IList list = parent as IList;
					if (base.IsTemplateMode && (list != null))
					{
						XmlAttribute node = xmlDocument.CreateAttribute("_Template_");
						if (list.Count == 1)
						{
							node.Value = "All";
						}
						else
						{
							node.Value = list.IndexOf(objectToSerialize).ToString(CultureInfo.InvariantCulture);
						}
						newChild.Attributes.Append(node);
						flag = true;
					}
					PropertyInfo[] properties = objectToSerialize.GetType().GetProperties();
					if (properties != null)
					{
						foreach (PropertyInfo info in properties)
						{
							if ((!flag || (info.Name != "Name")) && (!base.IsChartBaseProperty(objectToSerialize, parent, info) && base.IsSerializableContent(info.Name, objectToSerialize)))
							{
								if ((info.CanRead && (info.PropertyType.GetInterface("ICollection", true) != null)) && !base.SerializeICollAsAtribute(info, objectToSerialize))
								{
									bool flag2 = true;
									if (objectToSerialize != null)
									{
										PropertyDescriptor descriptor2 = TypeDescriptor.GetProperties(objectToSerialize)[info.Name];
										if (descriptor2 != null)
										{
											SerializationVisibilityAttribute attribute3 = (SerializationVisibilityAttribute)descriptor2.Attributes[typeof(SerializationVisibilityAttribute)];
											if ((attribute3 != null) && (attribute3.Visibility == SerializationVisibility.Hidden))
											{
												flag2 = false;
											}
										}
									}
									MethodInfo method = objectToSerialize.GetType().GetMethod("ShouldSerialize" + info.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
									if (method != null)
									{
										object obj2 = method.Invoke(objectToSerialize, null);
										if ((obj2 is bool) && !((bool)obj2))
										{
											flag2 = false;
										}
									}
									if (flag2)
									{
										this.SerializeCollection(info.GetValue(objectToSerialize, null), info.Name, newChild, xmlDocument);
									}
								}
								else if ((info.CanRead && info.CanWrite) && (info.Name != "Item"))
								{
									if (base.ShouldSerializeAsAttribute(info, objectToSerialize))
									{
										this.SerializeProperty(info.GetValue(objectToSerialize, null), objectToSerialize, info.Name, newChild, xmlDocument);
									}
									else
									{
										this.SerializeObject(info.GetValue(objectToSerialize, null), objectToSerialize, info.Name, newChild, xmlDocument);
									}
								}
							}
						}
					}
				}
			}
		}

		protected virtual void SerializeProperty(object objectToSerialize, object parent, string elementName, XmlNode xmlParentNode, XmlDocument xmlDocument)
		{
			if ((objectToSerialize != null) && (parent != null))
			{
				PropertyDescriptor descriptor = TypeDescriptor.GetProperties(parent)[elementName];
				if (descriptor != null)
				{
					DefaultValueAttribute attribute = (DefaultValueAttribute)descriptor.Attributes[typeof(DefaultValueAttribute)];
					if (attribute != null)
					{
						if (objectToSerialize.Equals(attribute.Value))
						{
							return;
						}
					}
					else
					{
						MethodInfo method = parent.GetType().GetMethod("ShouldSerialize" + elementName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
						if (method != null)
						{
							object obj2 = method.Invoke(parent, null);
							if ((obj2 is bool) && !((bool)obj2))
							{
								return;
							}
						}
					}
					SerializationVisibilityAttribute attribute2 = (SerializationVisibilityAttribute)descriptor.Attributes[typeof(SerializationVisibilityAttribute)];
					if ((attribute2 != null) && (attribute2.Visibility == SerializationVisibility.Hidden))
					{
						return;
					}
				}
				XmlAttribute node = xmlDocument.CreateAttribute(elementName);
				node.Value = this.GetXmlValue(objectToSerialize, parent, elementName);
				xmlParentNode.Attributes.Append(node);
			}
		}

		private void SetXmlValue(object obj, string attrName, string attrValue)
		{
			PropertyInfo property = obj.GetType().GetProperty(attrName);
			if (property != null)
			{
				object obj2 = attrValue;
				if (property.PropertyType == typeof(string))
				{
					obj2 = attrValue;
				}
				else if (property.PropertyType == typeof(Font))
				{
					obj2 = SerializerBase.FontFromString(attrValue);
				}
				else if (property.PropertyType == typeof(Color))
				{
					obj2 = (Color)SerializerBase.colorConverter.ConvertFromString(null, CultureInfo.InvariantCulture, attrValue);
				}
				else if (property.PropertyType == typeof(Unit))
				{
					obj2 = new Unit(int.Parse(attrValue, CultureInfo.InvariantCulture));
				}
				else if (property.PropertyType == typeof(System.Drawing.Image))
				{
					obj2 = SerializerBase.ImageFromString(attrValue);
				}
				else
				{
					PropertyDescriptor pd = TypeDescriptor.GetProperties(obj)[attrName];
					if (pd != null)
					{
						TypeConverter converter = base.FindConverter(pd);
						if ((converter != null) && converter.CanConvertFrom(typeof(string)))
						{
							obj2 = converter.ConvertFromString(null, CultureInfo.InvariantCulture, attrValue);
						}
					}
				}
				property.SetValue(obj, obj2, null);
			}
			else if (!base.IsUnknownAttributeIgnored)
			{
				throw new InvalidOperationException(SR.ExceptionChartSerializerPropertyNameUnknown(attrName, obj.GetType().ToString()));
			}
		}
	}
}

